﻿using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using Librarinth;

using SunwellRenderer.Simulation;

namespace SunwellRenderer.Rendering
{
	public struct BasicMaterial
	{
		public Texture Texture;
		public Texture Normal;
		public Texture Height;
		public Texture Alpha;
		public Texture Specular;
		public Texture Noise;
		public Texture Emissive;

		public static void FromMesh(ModelMesh mesh,int effectIndex,out BasicMaterial material)
		{
			material.Texture	= mesh.Effects[effectIndex].Parameters["Texture"].GetValueTexture2D();
			material.Normal	= mesh.Effects[effectIndex].Parameters["NormalMap"].GetValueTexture2D();
			material.Height	= mesh.Effects[effectIndex].Parameters["HeightMap"].GetValueTexture2D();
			material.Alpha	= mesh.Effects[effectIndex].Parameters["AlphaMap"].GetValueTexture2D();
			material.Specular	= mesh.Effects[effectIndex].Parameters["SpecularMap"].GetValueTexture2D();
			material.Noise	= mesh.Effects[effectIndex].Parameters["Noise"].GetValueTexture2D();
			material.Emissive	= mesh.Effects[effectIndex].Parameters["Emissive"].GetValueTexture2D();
		}
	}

	public abstract class BesicMaterialShader : ShaderEffect<BasicMaterial>
	{
		public BesicMaterialShader(string assetName) : base(assetName) { }
		protected override void OnDraw(GraphicsDevice device,int cameraIndex,BufferArray<int> dataIndexes)
		{
			var models	= Parent.AllModels.Datas;
			var spatial	= SunwellMain.Instance.SpatialModule;
			var materials	= DataPool<BasicMaterial>.Datas;

			var view	= Parent.CameraModule.View(cameraIndex);
			var viewProjection	= Parent.CameraModule.ViewProjection(cameraIndex);

			Effect.CurrentTechnique = Effect.Techniques["Full"];
			Effect.Begin();

			foreach(var dataIndex in dataIndexes)
			{
				var data	= Datas[dataIndex];
				var obj	= SunwellMain.Instance.Simulation.Datas[data.OBJIndex];

				Effect.Parameters["WorldView"].SetValue(spatial.Datas[obj.SpatialIndex].World * view);
				Effect.Parameters["WorldViewProjection"].SetValue(spatial.Datas[obj.SpatialIndex].World * viewProjection);

				Effect.Parameters["Texture"].SetValue(materials[data.MaterialIndex].Texture);
				Effect.Parameters["NormalMap"].SetValue(materials[data.MaterialIndex].Normal);
				Effect.Parameters["SpecularMap"].SetValue(materials[data.MaterialIndex].Specular);
				Effect.Parameters["Emissive"].SetValue(materials[data.MaterialIndex].Emissive);
				Effect.Parameters["HeightMap"].SetValue(materials[data.MaterialIndex].Height);
				Effect.Parameters["AlphaMap"].SetValue(materials[data.MaterialIndex].Alpha);
				Effect.Parameters["Noise"].SetValue(materials[data.MaterialIndex].Noise);

				Effect.CommitChanges();

				Parent.DrawMesh(device,Effect,models[data.ModelIndex].Model.Meshes[data.MeshIndex]);
			}

			Effect.End();
		}
	}

	public class BetaShader : BesicMaterialShader
	{
		public BetaShader() : base("HEXcontent/FX/SHADER/HCShader_beta") { }
	}

	public class LeafShader : BesicMaterialShader
	{
		public LeafShader() : base("HEXcontent/FX/SHADER/Shader_Leaf") { }
	}
}
